package GameMaster

import (
	codecs "sanguo/codec/cs"
	"sanguo/node/common/GlobalConstData"
	"sanguo/node/common/attr"
	"sanguo/node/common/com_type"
	"sanguo/node/common/transaction"
	"sanguo/node/node_game"
	"sanguo/node/node_game/module/role"
	"sanguo/node/node_game/user"
	table_RoleLevel "sanguo/node/table/excel/table/RoleLevel"
	cs_message "sanguo/protocol/cs/message"
	"time"

	"github.com/golang/protobuf/proto"
)

type transactionGameMaster struct {
	transaction.TransactionBase
	user    *user.User
	req     *codecs.Message
	resp    *cs_message.GameMasterToC
	errcode cs_message.EnumType
}

func (this *transactionGameMaster) GetModuleName() string {
	return "GameMonster"
}

func (this *transactionGameMaster) GetReplyMsg() proto.Message {
	return &cs_message.GameMasterToC{}
}

func (this *transactionGameMaster) SetExpiredTime(expired time.Time) {
	this.Expired = expired
}

func (this *transactionGameMaster) GetExpiredTime() time.Time {
	return this.Expired
}

func (this *transactionGameMaster) Begin() {

	this.resp = &cs_message.GameMasterToC{}
	msg := this.req.GetData().(*cs_message.GameMasterToS)
	roleModule := this.user.GetModuleByName("role").(*role.RoleModule)
	role := roleModule.CurrentRole()

	if role == nil || !role.IsRoleModleData() {
		node_game.Infoln(role.GetUserID(), "GameMaster : role is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}
	node_game.Infof("%s %d Call GameMaster type:%d id:%d count:%d", role.GetUserID(), role.GetID(), msg.GetType(), msg.GetID(), msg.GetCount())

	if !GlobalConstData.GameMaster {
		node_game.Infoln(role.GetUserID(), role.GetID(), "GameMaster Fail: false")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	switch msg.GetType() {
	case com_type.GMCommond_ModifyUsualAttr:
		if msg.GetID() == attr.ActionPoint {
			role.GetRoleAttr().AddAttr(msg.GetID(), int64(msg.GetCount()), 0, GlobalConstData.ActionPointMax)
		} else if msg.GetID() == attr.Level {
			roleLevel, _ := role.GetRoleAttr().GetAttr(attr.Level)
			exp := int64(0)
			for i := int64(0); i < int64(msg.GetCount()); i++ {
				level := roleLevel + i
				exp += int64(table_RoleLevel.Table_.IDMap[int32(level)].Exp)
			}
			role.AddExp(exp)

		} else if msg.GetID() == attr.TotalExp {
			role.AddExp(int64(msg.GetCount()))
		} else {
			role.GetRoleAttr().AddAttr(msg.GetID(), int64(msg.GetCount()), 0, 9999999999)
		}

	case com_type.GMCommond_ModifyBattleAttr:
		role.GetRoleBattleAttr().AddBattleAttr(msg.GetID(), msg.GetCount())
		role.OnBattleAttrDirty()
	case com_type.GMCommond_AddSoul:
		souls := map[int32]int32{
			msg.GetID(): msg.GetCount(),
		}
		role.AddSoul(souls)

	case com_type.GMCommond_AddItem:
		items := map[int32]int32{
			msg.GetID(): msg.GetCount(),
		}
		role.AddItem(items)
	case com_type.GMCommond_AddWeapon:
		weapons := map[int32]int32{
			msg.GetID(): msg.GetCount(),
		}
		role.AddWeapon(weapons)
	case com_type.GMCommond_AddWeaponShard:
		ws := map[int32]int32{
			msg.GetID(): msg.GetCount(),
		}
		role.AddWeaponShard(ws)
	case com_type.GMCommond_AddStarStone:
		role.AddStarMoon(msg.GetCount())
	case com_type.GMCommond_GetMission:
		mission := role.GetRoleMission().GetMission(msg.GetID())
		if mission == nil {
			role.GetRoleMission().AddNextMission(msg.GetID())
		} else {
			delete(role.GetRoleMission().GetMissions(), mission.GetMissionId())
			role.GetRoleMission().AddNextMission(msg.GetID())
		}
	default:
		node_game.Infoln("GameMaster err type")
	}

	node_game.Infoln(role.GetUserID(), role.GetID(), msg.GetType(), msg.GetID(), msg.GetCount(), "GameMaster OK")
	this.errcode = cs_message.EnumType_OK
	this.user.EndTrans(this)
}

func (this *transactionGameMaster) End() {
	this.resp.Errcode = cs_message.EnumType(this.errcode).Enum()
	this.user.Reply(this.req.GetSeriNo(), this.resp)
}

func (this *transactionGameMaster) Timeout() {
	this.resp.Errcode = cs_message.EnumType(cs_message.EnumType_RETRY).Enum()
	this.user.EndTrans(this)
}

func init() {
	user.RegisterTransFunc(&cs_message.GameMasterToS{}, func(user *user.User, msg *codecs.Message) transaction.Transaction {
		return &transactionGameMaster{
			user: user,
			req:  msg,
		}
	})
}
